/***************************************************************************
 *   Copyright (C) 2007 by saa   *
 *   root@saa   *
 ***************************************************************************/

#include <QFileDialog>

#include "newsessionform.h"
#include "ui_new_target_form.h"
#include "utils.h"
#include "mainstream.h"
#include "database.h"


NewSessionForm::NewSessionForm(QWidget * parent ) : QDialog( parent )
{
    setupUi( this );

    connect(&MS, SIGNAL(logProgrammeMessage(const QString&, const LogFlag::LogLevels)),\
            this, SLOT(logProgrammeMessage(const QString&, const LogFlag::LogLevels)));
    connect(&MS, SIGNAL(showLinks( const LinkList&)), this, SLOT(showLinks(const LinkList &)));
    connect(&MS, SIGNAL(oneTracerouteFinished()), this, SLOT(tracerouteToTargetFinished()));
    connect(&MS, SIGNAL(telnetClientFinished()), this, SLOT(telnetClientFinished()));


    connect(startPB, SIGNAL(clicked()), this, SLOT(start()));
    connect(addTargetPB, SIGNAL(clicked()), this, SLOT(addNewTargetClicked()));
    connect(removeTargetPB, SIGNAL(clicked()), this, SLOT(removeSelectedTarget()));
    connect(saveLinksPB, SIGNAL(clicked()), this, SLOT(saveLinkToDB()));
    connect(removeLinkPB, SIGNAL(clicked()), this, SLOT(removeLink()));
    
    connect(telnetClientLogCheckBox, SIGNAL(stateChanged(int)), this, SLOT(changeTelnetClientLogLevel(const int)));
    connect(parserLogCheckBox, SIGNAL(stateChanged(int)), this, SLOT(changeParserLogLevel( const int)));
    connect(databaseLogCheckBox, SIGNAL(stateChanged(int)), this, SLOT(changeDatabaseLogLevel( const int)));

    linkTableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("begin")));
    linkTableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("end")));
    linkTableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("average time")));
    linkTableWidget->setHorizontalHeaderItem(3, new QTableWidgetItem(tr("count")));
    for(int i = 0; i < 4; ++i)
        linkTableWidget->resizeColumnToContents(i);

    targetTableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("name")));
    targetTableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("IP")));
    for(int i = 0; i < 2; ++i)
        targetTableWidget->resizeColumnToContents(i);

    progressBar = new QProgressBar(this);
    progressBar->setMinimum(0);
    progressBar->setMaximum(0);
    progressBar->setValue(0);
    progressBar->hide();

    statusBar = new QStatusBar(this);
    statusBar->setSizeGripEnabled(false);        
    statusBar->addPermanentWidget(progressBar, 1);
    statusBarLayout->addWidget(statusBar);    

    activeLookup = 0;
    started = false;
    targetCount = 0;

    startPB->setEnabled(false);
}

void NewSessionForm::start()
{
    if(!started) {

        QString fileName = QFileDialog::getOpenFileName( this, tr("Select routeserver database file"));
        if(fileName.isEmpty())
            return;

        QList<RouteServer> routeServerList;
        DB.getRouteServerList(fileName, &routeServerList);
        if(routeServerList.isEmpty()){
            QMessageBox::warning(this, tr("Database file error"), tr("Database file corrupted"));
            return;
        }

        QStringList targetList;
        for(int i = 0; i < targetTableWidget->rowCount(); ++i)
            targetList.append((targetTableWidget->item(i, 1)->text()));
        targetCount = targetList.size();
        
        logMessage.clear();
        logTextEdit->clear();
        linkTableWidget->clearContents();
        linkTableWidget->setRowCount(0);        
        MS.start(routeServerList, targetList);

        startPB->setText(tr("Stop"));
        addTargetPB->setEnabled(false);
        removeTargetPB->setEnabled(false);

        progressBar->setVisible(true);
        progressBar->setMaximum(routeServerList.count() * targetList.count());
        progressBar->setValue(0);

        started = true;

    } else {
        startPB->setText(tr("Start"));
        removeTargetPB->setEnabled(true);
        addTargetPB->setEnabled(true);
        progressBar->setVisible(false);
        emit stop();
        started = false;
    }
}


void NewSessionForm::tracerouteToTargetFinished()
{
    progressBar->setValue(progressBar->value() + 1);
}

void NewSessionForm::telnetClientFinished()
{
    progressBar->setValue(progressBar->value() + targetCount);
}

void NewSessionForm::saveLinkToDB()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save links"));
    if(fileName.isEmpty())
        return;

    LinkList linkList;
    for(int i = 0; i < linkTableWidget->rowCount(); ++i){
        linkList.append(Link(QHostAddress(linkTableWidget->item(i, 0)->text()).toIPv4Address(), // begin
                             QHostAddress(linkTableWidget->item(i, 1)->text()).toIPv4Address(), // end
                             linkTableWidget->item(i, 2)->text().toDouble(), // average time
                             linkTableWidget->item(i, 3)->text().toInt())); // node count
    }
    DB.saveLinks(fileName, linkList);
}

void NewSessionForm::removeLink()
{
    QList<QTableWidgetItem *> selectedItems(linkTableWidget->selectedItems());
    for(QList<QTableWidgetItem *>::iterator i = selectedItems.begin(); i != selectedItems.end(); ++i)
        linkTableWidget->removeRow((*i)->row());
}

void NewSessionForm::logProgrammeMessage( const QString & message, const LogFlag::LogLevels logLevel )
{
    logMessage.append(LogMessage(message, logLevel));
    if(int(logLevel & m_logLevel))
        logTextEdit->append(QTime::currentTime().toString() + " " + message);
}

void NewSessionForm::changeTelnetClientLogLevel( const int state )
{
    changeLogLevel(LogFlag::TelnetClient, state);
}

void NewSessionForm::changeParserLogLevel( const int state )
{
    changeLogLevel(LogFlag::Parser, state);
}

void NewSessionForm::changeDatabaseLogLevel( const int state )
{
    changeLogLevel(LogFlag::Database, state);
}

void NewSessionForm::changeLogLevel( const LogFlag::LogLevels logLevel, const int state )
{
    if(state)
        m_logLevel |= logLevel;
    else
        m_logLevel &= ~logLevel;
    updateLogTextEdit( );
}

void NewSessionForm::updateLogTextEdit( )
{
    logTextEdit->clear();
    for(int i = 0; i < logMessage.size(); ++i)
        if(int(logMessage.at(i).logLevel & m_logLevel))
            logTextEdit->append(logMessage.at(i).message);
}

void NewSessionForm::showLinks( const LinkList & linkList )
{
    int row;
    for(int i = 0; i < linkList.size(); ++i){
        row = linkTableWidget->rowCount();
        linkTableWidget->insertRow(row);
        linkTableWidget->setItem(row, 0, new QTableWidgetItem(QHostAddress(linkList.at(i).begin).toString()));
        linkTableWidget->setItem(row, 1, new QTableWidgetItem(QHostAddress(linkList.at(i).end).toString()));
        linkTableWidget->setItem(row, 2, new QTableWidgetItem(QString::number(linkList.at(i).averageTime)));
        linkTableWidget->setItem(row, 3, new QTableWidgetItem(QString::number(linkList.at(i).nodeCount)));
    }
    linkTableWidget->resizeColumnToContents(0);
    linkTableWidget->resizeColumnToContents(1);
    linkTableWidget->resizeColumnToContents(2);
    linkTableWidget->resizeColumnToContents(3);
}

void NewSessionForm::addNewTargetClicked( )
{
    QDialog * window = new QDialog;
    Ui::new_target_form ui;
    ui.setupUi(window);
    if(window->exec()){
        QStringList tmpTargetList(ui.ipAddressTextEdit->toPlainText().split(QRegExp("\\s|\\n\\r|\\,|\\;|\\:"),
                                    QString::SkipEmptyParts));
        QStringList targetList;
        for(int i = 0; i < tmpTargetList.size();++i)
            targetList.append(checkTarget(tmpTargetList.at(i)));

        for(int i = 0; i < targetList.size(); ++i) {
            startPB->setEnabled(false);
            QHostInfo::lookupHost(targetList.at(i), this, SLOT(addNewTarget(const QHostInfo &)));

            statusBar->showMessage(tr("Check targets..."));
            progressBar->setMaximum(++activeLookup);
            progressBar->setVisible(true);
        }
    }
    delete window;
}

void NewSessionForm::addNewTarget(const QHostInfo & hostInfo)
{
    progressBar->setValue(progressBar->value() + 1);
    if(!--activeLookup){
        statusBar->showMessage(tr("All targets checked"));
        progressBar->setVisible(false);
        progressBar->setValue(0);
    }

    if (hostInfo.error() != QHostInfo::NoError) {
        QMessageBox::warning(this, tr("Lookup error"),
                             hostInfo.errorString() + ": " + hostInfo.hostName(),
                             QMessageBox::Ok);
        return;
    }

    int row = targetTableWidget->rowCount();
    for(int i = 0; i < hostInfo.addresses().count(); ++i) {
        targetTableWidget->insertRow(row + i);
        targetTableWidget->setItem(row + i, 0, new QTableWidgetItem(hostInfo.hostName()));
        targetTableWidget->setItem(row + i, 1, new QTableWidgetItem(hostInfo.addresses().at(i).toString()));
    }
    targetTableWidget->resizeColumnToContents(0);
    targetTableWidget->resizeColumnToContents(1);
    startPB->setEnabled(true);
}

void NewSessionForm::removeSelectedTarget( )
{
    QList<QTableWidgetItem *> selectedItems(targetTableWidget->selectedItems());
    for(QList<QTableWidgetItem *>::iterator i = selectedItems.begin(); i != selectedItems.end(); ++i)
        targetTableWidget->removeRow((*i)->row());
    targetTableWidget->resizeColumnToContents(0);
    targetTableWidget->resizeColumnToContents(1);
    if(!targetTableWidget->rowCount())
        startPB->setEnabled(false);
}
